<template>
	<view class="record-handle">
		<view @touchstart="startRecordHandle" @touchend="endRecordHandle" @touchmove="moveHandle">按住 说话</view>
		<view class="record-panel" :class="[showRecordPanel?'show':'']" @touchend="endRecordHandle">
			<view class="wave" :class="[status?'on':'',canClean?'clean':'',canTransform?'transform':'']">
				<view class="run" v-if="!canTransform">
					<span></span>
					<span></span>
					<span></span>
					<span></span>
					<span></span>
				</view>
				<view class="word" v-if="canTransform">
					<text class="done" v-if="audioToWord">{{audioToWord}}</text>
					<block v-else>
						<text class="dot">·</text>
						<text class="dot">·</text>
						<text class="dot">·</text>
					</block>
				</view>
			</view>
			<view class="action clean" v-if="!transformStatus" :class="[canClean?'on':'']"></view>
			<text class="clean-tips tips" v-if="canClean">松开 取消</text>
			<view class="range" v-if="!transformStatus" :class="[canClean || canTransform?'on':'']"></view>
			<view class="iconfont icon-yuyin1 micro" v-if="transformStatus < 1"
				:class="[canClean || canTransform?'':'on']"></view>
			<view class="action transform" :class="[canTransform?'on':'']">
				<view v-if="transformStatus === 0" class="before">文</view>
				<view v-else-if="transformStatus === 1" class="iconfont icon-Loading"></view>
				<view v-else class="iconfont icon-duihao"></view>
			</view>
			<view class="btn cancel" v-if="transformStatus === 2" @click="cancelTransform"><text
					class="iconfont icon-chehui"></text><br />取消</view>
			<view class="btn send-audio" v-if="transformStatus === 2"><text
					class="iconfont icon-yuyin1"></text><br />发送原语音</view>
			<text class="transform-tips tips" v-if="canTransform && transformStatus!==2">转文字</text>
			<text class="send-tips tips" v-if="!canClean && !canTransform">松手 发送</text>
		</view>
	</view>
</template>

<script>
	import cache from '@/utils/cache';
	const transformToWord = () => {
		return new Promise((resolve) => {
			setTimeout(() => {
				resolve(true);
			}, 3000)
		})
	}
	const recorderManager = uni.getRecorderManager();
	const innerAudioContext = uni.createInnerAudioContext();
	innerAudioContext.autoplay = true;
	export default {
		name: 'record',
		data() {
			return {
				screenHeight: 0,
				screenWidth: 0,
				sW: 0,
				sH: 0,
				startTime: 0,
				showRecordPanel: false,
				canClean: false,
				canTransform: false,
				iNum: 0,
				hours: '00',
				min: '00',
				sec: '00',
				timer: null,
				status: 0,
				sourcePath: '',
				transformStatus: 0,
				audioToWord: ''
			}
		},
		methods: {
			doubleNumber(num) {
				if (num < 10) {
					return '0' + num
				} else {
					return num
				}
			},
			uploadMedia(file) {
				const uploadTask = uni.uploadFile({
					url: `${import.meta.env.VITE_SERVER_BASEURL}/oss/sysOss/upload`,
					// url: 'https://testappthwater.thwater.com:30080/api/oss/sysOss/upload',
					filePath: file.path,
					name: 'file',
					header: {
						'Authorization': cache.get('token')
					},
					success: (res) => {
						const fileDuration = this.iNum;
						this.reset()
						const resp = JSON.parse(res.data);
						if(resp.code !== 0){
							uni.showToast({
								title:resp.msg,
								icon:'none'
							})
							return;
						}
						file.src = resp.data.url

						this.$forceUpdate();
						this.$emit('send', {
							type: 3,
							fileUrl: file.src,
							fileDuration,
							content:'audio'
						})
					},
					fail(err) {
						uni.showToast({
							title:'上传失败',
							icon:'none'
						})
						this.reset()
						file.src = 'none'
					}
				})

				uploadTask.onProgressUpdate((res) => {
					file.progress = res.progress;
				});

			},
			start() {
				this.timer = setInterval(() => {
					this.iNum++;
					this.sec = this.doubleNumber(this.iNum % 60)
					this.min = this.doubleNumber(parseInt((this.iNum / 60) % 60))
					this.hours = this.doubleNumber(parseInt((this.iNum / 3600) % 60))
				}, 1000)
			},
			startRecordHandle(e) {
				// 容易触发系统事件
				if (this.screenHeight - e.touches[0].pageY < 15) return;
				this.startTime = new Date().getTime();
				if (this.status) return;
				this.status = 1;
				this.showRecordPanel = true;
				uni.vibrateShort();
				recorderManager.start({
					sampleRate: 16000,
					format: 'mp3'
				});
				this.start();
			},
			endRecordHandle() {
				console.log(111)
				// 如果点击速度过快则，手动清除
				if (new Date().getTime() - this.startTime < 150) {
					setTimeout(() => {
						this.reset();
					}, 500)
				}
				recorderManager.stop();
			},
			moveHandle(e) {
				const {
					pageX,
					pageY
				} = e.changedTouches[0];
				if ((pageX <= this.sW && pageY < this.sH) || pageX < 100) {
					this.canClean = true;
				} else {
					this.canClean = false;
				}
				if ((pageX > this.sW && pageY < this.sH) || pageX > this.screenWidth - 100) {
					// this.canTransform = true;
					this.canTransform = false;
				} else {
					this.canTransform = false;
				}
			},
			reset() {
				innerAudioContext.pause();
				this.status = 0;
				this.sourcePath = ''
				this.hours = '00'
				this.min = '00'
				this.sec = '00'
				this.iNum = 0;
				this.canClean = false;
				this.canTransform = false;
				this.audioToWord = '';
				this.transformStatus = 0;
				this.showRecordPanel = false;
				clearInterval(this.timer)
			},
			cancelTransform() {
				this.reset()
			}
		},
		mounted() {
			const {
				screenHeight,
				screenWidth,
				safeArea
			} = uni.getSystemInfoSync();
			this.screenHeight = screenHeight;
			this.screenWidth = screenWidth;
			this.sH = safeArea.height - 120;
			this.sW = safeArea.width * 0.6;

			recorderManager.onStop(async (res) => {
				this.sourcePath = res.tempFilePath;
				// 判断取消、转成文字、发送
				if (this.canClean) {
					this.showRecordPanel = false;
					this.reset();
					return;
				} else if (this.canTransform) {
					// 转文字
					if (this.iNum < 1) {
						uni.showToast({
							title: '说话时间太短',
							icon: 'error'
						})
						this.reset()
						return;
					}
					// 语音识别
					this.transformStatus = 1
					const audioToWord = await transformToWord();
					if (audioToWord) {
						this.audioToWord = ''
						this.transformStatus = 2;
					}

					return;
				} else {
					// 发送
					if (this.iNum < 1) {
						uni.showToast({
							title: '说话时间太短',
							icon: 'error'
						})
						this.reset()
					} else {
						this.sourcePath = res.tempFilePath;
						const tempFile = {
							progress: 0,
							path: this.sourcePath,
							play: false,
							type: 'voice'
						}
						this.uploadMedia(tempFile);
					}
				}
			});
		}
	}
</script>

<style lang="scss">
	@import url('@/static/iconfont/iconfont.css');

	.record-handle {
		flex: 1;
		height: 78rpx;
		line-height: 78rpx;
		text-align: center;
		margin-right: 10rpx;
		margin-left: 10rpx;
		background: #fff;
		border-radius: 10rpx;
	}

	.record-panel {
		width: 100vw;
		height: 100vh;
		background: rgba(0, 0, 0, 0.5);
		position: fixed;
		z-index: 99999;
		left: 0;
		bottom: 0;
		color: #fff;
		visibility: hidden;
		opacity: 0;
		transition: .5s all;

		&.show {
			visibility: visible;
			opacity: 1;
		}

		.wave {
			width: 360rpx;
			background: #95ec69;
			position: absolute;
			bottom: 660rpx;
			border-radius: 30rpx;
			left: 50%;
			transform: translate(-50%);
			transition: all .3s;

			.run {
				width: 100%;
				height: 180rpx;
				display: flex;
				align-items: center;
				justify-content: center;
			}

			.word {
				height: 180rpx;
				text-align: left;
				padding: 30rpx;
				line-height: 40rpx;

				.done {
					color: #000;
				}
			}

			&::before {
				content: '';
				width: 25rpx;
				height: 25rpx;
				border-radius: 6rpx;
				position: absolute;
				transform: rotate(-45deg) translateX(-50%);
				left: 50%;
				bottom: -3rpx;
				background: inherit;
				z-index: 99999;
			}

			&.clean {
				background: #FA5151;
				left: 30px;
				transform: translate(0);
				width: 180rpx;
			}

			&.transform {
				width: 690rpx;

				&::before {
					left: calc(100% - 130rpx);
				}
			}

			span {
				display: inline-block;
				width: 6rpx;
				height: 30rpx;
				border-radius: 4rpx;
				background: #fff;
				margin: 0 10rpx;
			}

			&.on {
				opacity: 1;

				span {
					animation: load .8s ease infinite;
				}
			}

			span:nth-child(2) {
				animation-delay: 0.13s;
			}

			span:nth-child(3) {
				animation-delay: 0.26s;
			}

			span:nth-child(4) {
				animation-delay: 0.39s;
			}

			span:nth-child(5) {
				animation-delay: 0.52s;
			}
		}

		.action {
			width: 120rpx;
			height: 120rpx;
			background: rgba(0, 0, 0, 0.3);
			border-radius: 50%;
			position: absolute;
			bottom: 320rpx;
			transition: all cubic-bezier(0.075, 0.82, 0.165, 1) .4s;

			&.clean {
				left: 100rpx;

				&::before {
					content: '';
					width: 45rpx;
					height: 5rpx;
					background: #ccc;
					position: absolute;
					left: 50%;
					top: 50%;
					transform: translate(-50%, -50%) rotate(-75deg);
				}

				&::after {
					content: '';
					width: 45rpx;
					height: 5rpx;
					background: #ccc;
					position: absolute;
					left: 50%;
					top: 50%;
					transform: translate(-50%, -50%) rotate(20deg);
				}

				&.on {
					background: #fff;
					color: #000;
					transform: scale(1.2);

					&::before,
					&::after {
						background: #000;
					}
				}
			}


			&.transform {
				right: 100rpx;
				line-height: 120rpx;
				text-align: center;
				color: #8a8a8a;
				font-size: 40rpx;
				display: flex;
				justify-content: center;
				align-items: center;

				.before {
					transform: rotate(15deg);
				}

				.icon-Loading {
					color: #333;
					font-size: 40rpx !important;
					animation: rotate .9s linear infinite;
				}

				.icon-duihao {
					color: #07c160;
					font-size: 40rpx !important;
				}

				&.on {
					background: #fff;
					color: #000;
					transform: scale(1.3);

					.wen {
						transform: rotate(15deg);
					}
				}
			}
		}

		.btn {
			position: absolute;
			bottom: 320rpx;
			left: 130rpx;
			line-height: 45rpx;
			font-size: 30rpx;

			.iconfont {
				font-size: 40rpx !important;
			}

			&.cancel {
				left: 130rpx;
			}

			&.send-audio {
				left: 50%;
				transform: translateX(-50%);
			}
		}


		.range {
			width: 600px;
			height: 200px;
			border-radius: 50%;
			background: #f1f1f1;
			position: absolute;
			bottom: -70px;
			left: 50%;
			transform: translateX(-50%);
			transition: all .3s;
			box-shadow: 0 0 80rpx 1rpx rgba(0, 0, 0, 0.2) inset;
			border-top: 8rpx solid #fff;

			&.on {
				background: rgba(0, 0, 0, 0.2);
				bottom: -75px;
				border-top: none;
				box-shadow: none;
			}
		}

		.micro {
			position: absolute;
			left: 50%;
			transform: translateX(-50%);
			bottom: 95rpx;
			color: rgba(255, 255, 255, 0.4);
			font-size: 50rpx !important;

			&.on {
				color: rgba(0, 0, 0, 0.6);
			}
		}

		.tips {
			position: absolute;
			bottom: 450rpx;
			font-size: 26rpx;
			color: #ccc;
		}

		.clean-tips {
			left: 105rpx;
		}

		.transform-tips {
			right: 123rpx;
		}

		.send-tips {
			bottom: 130px;
			left: 50%;
			transform: translateX(-50%);
		}
	}

	@keyframes load {

		0%,
		100% {
			height: 30rpx;
		}

		50% {
			height: 40rpx;
		}
	}

	.loading span:nth-child(2) {
		animation-delay: 0.13s;
	}

	.loading span:nth-child(3) {
		animation-delay: 0.26s;
	}

	.loading span:nth-child(4) {
		animation-delay: 0.39s;
	}

	.loading span:nth-child(5) {
		animation-delay: 0.52s;
	}

	@keyframes opacityAni {

		0% {
			opacity: 0;
		}

		100% {
			opacity: 1;
		}
	}

	.dot {
		font-size: 40rpx;
		margin: 0 5rpx;
		color: #bfbfbf;
	}

	.dot:nth-child(2) {
		animation: opacityAni 1s ease infinite .2s;
	}

	.dot:nth-child(3) {
		animation: opacityAni 1s ease infinite .4s;
	}

	@keyframes rotate {
		from {
			transform: rotate(0deg);
		}

		to {
			transform: rotate(360deg);
		}
	}
</style>